using DevExpress.XtraEditors;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using twistmachinev2.CommonUse;
using twistmachinev2.OPCUA;
using twistmachinev2.Entity;
using twistmachinev2.TwistControl;

namespace twistmachinev2
{
    public partial class FrmSystemSettings : BaseOpcUaForm
    {
        public FrmSystemSettings()
        {
            InitializeComponent();
            LoadConfigData();
            InitialDataModel();
            RegisterDataBindingButtonEvents();
        }

        /// <summary>
        /// 初始化DataModel绑定
        /// </summary>
        private void InitialDataModel()
        {
            var dataModel = GetDataModel("TwistMachine");

            // 遍历所有控件，为DataBindingTextBox和DataBindingButton类型的控件设置DataModel
            SetDataModelForControls(this, dataModel);
        }

        /// <summary>
        /// 递归遍历控件及其子控件，为DataBindingTextBox和DataBindingButton类型的控件设置DataModel
        /// </summary>
        /// <param name="parent">父控件</param>
        /// <param name="dataModel">数据模型</param>
        private void SetDataModelForControls(Control parent, DynamicDataModel dataModel)
        {
            foreach (Control control in parent.Controls)
            {
                // 检查控件类型是否为DataBindingTextBox
                if (control is TwistControl.DataBindingTextBox textBox && !string.IsNullOrEmpty(textBox.PropertyName))
                {
                    textBox.DataModel = dataModel;
                }
                // 检查控件类型是否为DataBindingButton
                else if (control is TwistControl.DataBindingButton button && !string.IsNullOrEmpty(button.PropertyName))
                {
                    button.DataModel = dataModel;
                    button.AutoUpdate = true; // 启用自动更新
                }
                // 检查控件类型是否为DataBindingStatusCircle
                else if (control is TwistControl.DataBindingStatusCircle statusCircle && !string.IsNullOrEmpty(statusCircle.PropertyName))
                {
                    statusCircle.DataModel = dataModel;
                }

                // 递归处理子控件
                if (control.HasChildren)
                {
                    SetDataModelForControls(control, dataModel);
                }
            }
        }

        /// <summary>
        /// 注册所有DataBindingButton控件的点击事件
        /// </summary>
        private void RegisterDataBindingButtonEvents()
        {
            // 遍历窗体中的所有DataBindingButton控件
            RegisterDataBindingButtonEventsRecursive(this);
        }

        /// <summary>
        /// 递归遍历控件并注册DataBindingButton的点击事件
        /// </summary>
        /// <param name="parent">父控件</param>
        private void RegisterDataBindingButtonEventsRecursive(Control parent)
        {
            foreach (Control control in parent.Controls)
            {
                // 检查控件类型是否为DataBindingButton
                if (control is TwistControl.DataBindingButton dataBindingButton)
                {
                    // 注册点击事件
                    dataBindingButton.Click += DataBindingButton_Click;
                }

                // 递归处理子控件
                if (control.HasChildren)
                {
                    RegisterDataBindingButtonEventsRecursive(control);
                }
            }
        }

        /// <summary>
        /// DataBindingButton点击事件处理
        /// </summary>
        /// <param name="sender">发送者</param>
        /// <param name="e">事件参数</param>
        private async void DataBindingButton_Click(object sender, EventArgs e)
        {
            // 将sender转换为DataBindingButton
            if (sender is TwistControl.DataBindingButton button)
            {
                // 获取PropertyName属性
                string propertyName = button.PropertyName;
                
                if (!string.IsNullOrEmpty(propertyName))
                {
                    // 根据PropertyName获取对应的OPC UA NodeId
                    var nodeConfig = GetNodeConfigByPropertyName(propertyName);
                    
                    if (nodeConfig != null)
                    {
                        try
                        {
                            // 检查节点是否可写
                            if (nodeConfig.AccessLevel.Contains("Write"))
                            {
                                // 从控件DataModel中获取当前值并进行取反操作
                                await ToggleOpcUaNodeValue(button, nodeConfig.NodeId);
                            }
                            else
                            {
                                MessageBox.Show($"节点 {nodeConfig.NodeId} 不可写", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                            }
                        }
                        catch (Exception ex)
                        {
                            LogManager.LogError($"DataBindingButton点击事件处理异常：{ex.Message}");
                            MessageBox.Show($"操作失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                    else
                    {
                        MessageBox.Show($"未找到PropertyName '{propertyName}' 对应的节点配置", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                }
                else
                {
                    MessageBox.Show("按钮的PropertyName为空", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
        }

        /// <summary>
        /// 从控件DataModel中获取当前值并进行取反写入操作
        /// </summary>
        /// <param name="button">DataBindingButton控件</param>
        /// <param name="nodeId">节点ID</param>
        private async Task ToggleOpcUaNodeValue(TwistControl.DataBindingButton button, string nodeId)
        {
            try
            {
                // 从DataModel中获取当前值
                 if (button.DataModel != null && !string.IsNullOrEmpty(button.PropertyName))
                 {
                     var currentValue = button.DataModel.GetValue(button.PropertyName);
                    
                    // 对于布尔值进行取反操作
                    bool newValue = false;
                    if (currentValue is bool boolValue)
                    {
                        newValue = !boolValue;
                    }
                    else if (currentValue != null)
                    {
                        // 尝试将其他类型转换为布尔值
                        if (bool.TryParse(currentValue.ToString(), out bool parsedValue))
                        {
                            newValue = !parsedValue;
                        }
                        else
                        {
                            // 如果无法解析为布尔值，则默认设置为true
                            newValue = true;
                        }
                    }
                    else
                    {
                        // 如果当前值为null，则设置为true
                        newValue = true;
                    }

                    // 写入新值到OPC UA节点
                    var result = await OpcUaServiceManager.Instance.WriteNodeAsync(nodeId, newValue);
                    if (!result.IsSuccess)
                    {
                        LogManager.LogError($"写入节点 {nodeId} 失败：{result.Message}");
                        MessageBox.Show($"写入失败：{result.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
                else
                {
                    MessageBox.Show("DataModel未设置或PropertyName为空", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
            catch (Exception ex)
            {
                LogManager.LogError($"切换节点 {nodeId} 值时发生异常：{ex.Message}");
                MessageBox.Show($"操作异常：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 监听数据变化事件
        /// </summary>
        /// <param name="nodeId">节点ID</param>
        /// <param name="value">变化的值</param>
        protected override void OnDataChangedOnUIThread(string nodeId, object value)
        {
            // 可以在这里处理特定节点的数据变化
            // 例如：
            // switch (nodeId)
            // {
            //     case "ns=2;s=SystemSettings.Parameter1":
            //         // 处理参数1变化
            //         break;
            //     case "ns=2;s=SystemSettings.Parameter2":
            //         // 处理参数2变化
            //         break;
            // }
        }

        /// <summary>
        /// 加载配置数据到界面
        /// </summary>
        private void LoadConfigData()
        {
            try
            {
                // 加载SystemName配置
                txtSystemName.Text = BaseData.GetSystemName();
                
                // 加载OPCUADatabase配置
                txtOPCUADatabase.Text = BaseData.GetOPCUADatabaseConfig();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载配置失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 刷新配置按钮点击事件
        /// </summary>
        private void btnRefreshConfig_Click(object sender, EventArgs e)
        {
            LoadConfigData();
            MessageBox.Show("配置已刷新", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        /// <summary>
        /// 保存配置按钮点击事件
        /// </summary>
        private void btnSaveConfig_Click(object sender, EventArgs e)
        {
            try
            {
                // 保存SystemName配置
                BaseData.UpdateAppSetting("SystemName", txtSystemName.Text.Trim());
                
                // 保存OPCUADatabase配置
                BaseData.UpdateConnectionString("OPCUADatabase", txtOPCUADatabase.Text.Trim());
                
                MessageBox.Show("配置保存成功！\n注意：部分配置可能需要重启应用程序后生效。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存配置失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 下发数据到PLC
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btnSend_Click(object sender, EventArgs e)
        {
            try
            {
                // 更新状态
                btnSend.Enabled = false;
                
                // 获取所有DataBindingTextBox控件
                var textBoxes = GetAllDataBindingTextBoxes();
                if (textBoxes.Count == 0)
                {
                    MessageBox.Show("未找到任何数据绑定文本框", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                // 准备要写入的数据
                var writeOperations = new List<(string nodeId, object value, string controlName)>();

                foreach (var textBox in textBoxes)
                {
                    // 检查是否有绑定的属性名称
                    if (!string.IsNullOrEmpty(textBox.PropertyName))
                    {
                        // 获取对应的节点配置信息
                         var nodeConfig = GetNodeConfigByPropertyName(textBox.PropertyName);
                         if (nodeConfig != null)
                         {
                             // 检查节点是否可写
                             if (nodeConfig.AccessLevel.Contains("Write"))
                             {
                                 // 获取当前文本框的值并根据节点数据类型进行转换
                                 var textValue = textBox.Text;
                                 object value = ConvertValueByDataType(textValue, nodeConfig.DataType);

                                 writeOperations.Add((nodeConfig.NodeId, value, textBox.Name));
                             }
                             else
                             {
                                 // 节点不可写，跳过写入操作
                             }
                         }
                    }
                }

                if (writeOperations.Count == 0)
                {
                    MessageBox.Show("没有找到可写入的数据", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                // 执行批量写入操作
                int successCount = 0;
                int failCount = 0;
                var errorMessages = new List<string>();

                foreach (var (nodeId, value, controlName) in writeOperations)
                {
                    try
                    {
                        var result = await OpcUaServiceManager.Instance.WriteNodeAsync(nodeId, value);
                        if (result.IsSuccess)
                         {
                             successCount++;
                             // 写入成功
                         }
                        else
                        {
                            failCount++;
                            var errorMsg = $"控件 {controlName} -> 节点 {nodeId}：{result.Message}";
                            errorMessages.Add(errorMsg);
                            LogManager.LogError($"写入失败 - {errorMsg}");
                        }
                    }
                    catch (Exception ex)
                    {
                        failCount++;
                        var errorMsg = $"控件 {controlName} -> 节点 {nodeId}：{ex.Message}";
                        errorMessages.Add(errorMsg);
                        LogManager.LogError($"写入异常 - {errorMsg}");
                    }
                }

                // 显示结果
                var resultMessage = $"数据下发完成！\n成功：{successCount} 项\n失败：{failCount} 项";
                if (errorMessages.Count > 0)
                {
                    resultMessage += $"\n\n失败详情：\n{string.Join("\n", errorMessages.Take(5))}";
                    if (errorMessages.Count > 5)
                    {
                        resultMessage += $"\n... 还有 {errorMessages.Count - 5} 项失败";
                    }
                }

                var icon = failCount == 0 ? MessageBoxIcon.Information : MessageBoxIcon.Warning;
                MessageBox.Show(resultMessage, "下发结果", MessageBoxButtons.OK, icon);

                // 数据下发完成
            }
            catch (Exception ex)
            {
                var exceptionMsg = $"下发数据时发生异常：{ex.Message}";
                LogManager.LogError(exceptionMsg);
                MessageBox.Show(exceptionMsg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                btnSend.Enabled = true;
             }
         }

        /// <summary>
        /// 获取所有非只读的DataBindingTextBox控件
        /// </summary>
        /// <returns></returns>
        private List<DataBindingTextBox> GetAllDataBindingTextBoxes()
        {
            var textBoxes = new List<DataBindingTextBox>();
            GetAllDataBindingTextBoxesRecursive(this, textBoxes);
            return textBoxes;
        }

        /// <summary>
        /// 递归获取所有DataBindingTextBox控件
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="textBoxes"></param>
        private void GetAllDataBindingTextBoxesRecursive(Control parent, List<DataBindingTextBox> textBoxes)
        {
            foreach (Control control in parent.Controls)
            {
                if (control is DataBindingTextBox textBox && !textBox.ReadOnly)
                {
                    textBoxes.Add(textBox);
                }
                else if (control.HasChildren)
                {
                    GetAllDataBindingTextBoxesRecursive(control, textBoxes);
                }
            }
        }

        /// <summary>
        /// 根据属性名称获取对应的OPC UA节点配置
        /// </summary>
        /// <param name="propertyName">属性名称</param>
        /// <returns>节点配置</returns>
        private OpcUaNodeConfigEntity GetNodeConfigByPropertyName(string propertyName)
        {
            try
            {
                // 从OPC UA配置服务中获取节点配置
                var configService = OpcUaServiceManager.Instance.ConfigService;
                if (configService == null)
                {
                    // OPC UA配置服务未初始化
                    return null;
                }

                // 获取所有节点配置
                var allNodes = configService.GetAllNodes();
                if (allNodes == null || allNodes.Count == 0)
                {
                    // 未找到任何OPC UA节点配置
                    return null;
                }

                // 根据PropertyName查找对应的节点配置
                var nodeConfig = allNodes.FirstOrDefault(n => n.PropertyName == propertyName);
                if (nodeConfig == null)
                {
                    // 未找到对应的节点配置
                    return null;
                }

                return nodeConfig;
            }
            catch (Exception ex)
            {
                LogManager.LogError($"获取PropertyName '{propertyName}' 对应的节点配置时发生异常：{ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 根据数据类型转换值
        /// </summary>
        /// <param name="textValue"></param>
        /// <param name="dataType"></param>
        /// <returns></returns>
        private object ConvertValueByDataType(string textValue, string dataType)
        {
            try
            {
                if (string.IsNullOrEmpty(textValue))
                {
                    // 文本值为空
                    return null;
                }

                switch (dataType?.ToUpper())
                {
                    case "BOOLEAN":
                    case "BOOL":
                        if (bool.TryParse(textValue, out bool boolValue))
                            return boolValue;
                        // 尝试数字转换 (0=false, 非0=true)
                        if (int.TryParse(textValue, out int intForBool))
                            return intForBool != 0;
                        LogManager.LogError($"无法将 '{textValue}' 转换为布尔值");
                        return false;

                    case "INT16":
                    case "SHORT":
                        if (short.TryParse(textValue, out short shortValue))
                            return shortValue;
                        LogManager.LogError($"无法将 '{textValue}' 转换为 Int16");
                        return (short)0;

                    case "INT32":
                    case "INT":
                        if (int.TryParse(textValue, out int intValue))
                            return intValue;
                        LogManager.LogError($"无法将 '{textValue}' 转换为 Int32");
                        return 0;

                    case "INT64":
                    case "LONG":
                        if (long.TryParse(textValue, out long longValue))
                            return longValue;
                        LogManager.LogError($"无法将 '{textValue}' 转换为 Int64");
                        return 0L;

                    case "UINT16":
                    case "USHORT":
                        if (ushort.TryParse(textValue, out ushort ushortValue))
                            return ushortValue;
                        LogManager.LogError($"无法将 '{textValue}' 转换为 UInt16");
                        return (ushort)0;

                    case "UINT32":
                    case "UINT":
                        if (uint.TryParse(textValue, out uint uintValue))
                            return uintValue;
                        LogManager.LogError($"无法将 '{textValue}' 转换为 UInt32");
                        return 0U;

                    case "UINT64":
                    case "ULONG":
                        if (ulong.TryParse(textValue, out ulong ulongValue))
                            return ulongValue;
                        LogManager.LogError($"无法将 '{textValue}' 转换为 UInt64");
                        return 0UL;

                    case "FLOAT":
                    case "SINGLE":
                        if (float.TryParse(textValue, out float floatValue))
                            return floatValue;
                        LogManager.LogError($"无法将 '{textValue}' 转换为 Float");
                        return 0.0f;

                    case "DOUBLE":
                        if (double.TryParse(textValue, out double doubleValue))
                            return doubleValue;
                        LogManager.LogError($"无法将 '{textValue}' 转换为 Double");
                        return 0.0;

                    case "STRING":
                    case "TEXT":
                        return textValue;

                    case "BYTE":
                        if (byte.TryParse(textValue, out byte byteValue))
                            return byteValue;
                        LogManager.LogError($"无法将 '{textValue}' 转换为 Byte");
                        return (byte)0;

                    case "SBYTE":
                        if (sbyte.TryParse(textValue, out sbyte sbyteValue))
                            return sbyteValue;
                        LogManager.LogError($"无法将 '{textValue}' 转换为 SByte");
                        return (sbyte)0;

                    default:
                        // 未知的数据类型，将作为字符串处理
                        return textValue;
                }
            }
            catch (Exception ex)
            {
                LogManager.LogError($"转换值时发生异常 - 值: '{textValue}', 类型: {dataType}, 错误: {ex.Message}");
                return textValue; // 转换失败时返回原始字符串
            }
        }
     }
 }
